package m

import (
	"GameServer/Common/data"
	"GameServer/Common/utils"
	"GameServer/Game/cache"
	"GameServer/Game/dbmodule"
	"GameServer/Game/errors"
	"fmt"
	"sort"
	"sync"

	"github.com/globalsign/mgo/bson"
	log "github.com/sirupsen/logrus"
)

// 奖励领取，奖励未领取，奖励激活。
// 存储数据库，存储缓存，存储上层数据
// 奖励，每个人都有一份数据
// 活动未开始，活动开始，活动持续，活动结束。活动激活。
// 通知用户，活动开始。活动属于所有人。奖励是每个人。

// 活动
type MCActiv struct {
	BaseM
	Uid          int64 `bson:"_id" json:"_id"`
	ActivityId   int64 `bson:"activityId" json:"activityId"`
	RankRewardId int64 `bson:"rankRewardId" json:"rankRewardId"`
	BeginTime    int64 `bson:"beginTime" json:"beginTime"`
	EndTime      int64 `bson:"endTime" json:"endTime"`
}

// Boss信息
type MCBoss struct {
	Tid int64 `bson:"tid" json:"tid"`
	Hp  int64 `bson:"hp" json:"hp"` // 血量
}

// 玩家组信息
type MCGamer struct {
	BaseM
	Uid           bson.ObjectId   `bson:"_id" json:"_id"` // 玩家uid
	Name          string          `bson:"name" json:"name"`
	Head          string          `bson:"head" json:"head"`
	AvatarFrame   int64           `bson:"avatarFrame" json:"avatarFrame"`
	LastRankId    int64           `bson:"lastRankId" json:"lastRankId"`       // 上次排名Id
	RankId        int64           `bson:"rankId" json:"rankId"`               // 排名Id
	Hurt          int64           `bson:"hurt" json:"hurt"`                   // 玩家累计伤害
	MEachBossHurt map[int64]int64 `bson:"mEachBossHurt" json:"mEachBossHurt"` // 每个Boss的累伤
	GroupTid      int64           `bson:"groupTid" json:"groupTid"`           // 小组Tid
	BossTid       int64           `bson:"bossTid" json:"bossTid"`             // bossTid
	IsRobot       int64           `bson:"isRobot" json:"isRobot"`             // 0-是机器人
}

// 小组
type MCGroup struct {
	BaseM
	Uid    int64             `bson:"_id" json:"_id"`
	MBoss  map[int64]*MCBoss `bson:"mBoss" json:"mBoss"`   // Boss信息 现在4只BOSS
	LGamer []*MCGamer        `bson:"lGamer" json:"lGamer"` // 小组中的100人信息（60人信息），排名，降序
	MGamer map[string]int64  `bson:"mGamer" json:"mGamer"` // 小组中玩家在列表中的索引位置
	rw     sync.RWMutex
}

// 初始化世界Boss玩家信息
func InitMCGamer(u *User) *MCGamer {
	return &MCGamer{
		Uid:           u.Uid,
		Name:          u.Name,
		Head:          u.Head,
		AvatarFrame:   u.AvatarFrame,
		LastRankId:    0,
		RankId:        0,
		Hurt:          0,
		MEachBossHurt: make(map[int64]int64),
		GroupTid:      0,
		BossTid:       0,
		IsRobot:       1,
	}
}

// 创建机器人
func NewMCGamerRobot() *MCGamer {
	return &MCGamer{
		Uid:           bson.NewObjectId(),
		Name:          fmt.Sprintf("%s", utils.GenName()),
		Head:          fmt.Sprintf("%s", utils.GenDefaultHead()),
		AvatarFrame:   data.AvatarFrameEnum.DefaultFrame,
		LastRankId:    0,
		RankId:        0,
		Hurt:          0,
		MEachBossHurt: make(map[int64]int64),
		GroupTid:      0,
		BossTid:       0,
		IsRobot:       0, // 标识为机器人
	}
}

// 小组：创建
func NewMCGroup() cache.EntryI {
	return &MCGroup{
		MBoss:  make(map[int64]*MCBoss, 0),
		LGamer: make([]*MCGamer, 0),
		MGamer: make(map[string]int64, 0),
	}
}

// 初始化小组
func InitMCGroup(uid int64) *MCGroup {
	return &MCGroup{
		Uid:    uid,
		MBoss:  make(map[int64]*MCBoss, 0),
		LGamer: make([]*MCGamer, 0),
		MGamer: make(map[string]int64, 0),
	}
}

// 小组：保存信息
func (mCGroup *MCGroup) Save() (err error) {
	err = dbmodule.MgoDB.GameDB.Upsert("MCGroup", bson.M{"_id": mCGroup.Uid}, mCGroup)
	if err != nil {
		return
	}
	return
}

// 小组：加载
func (mCGroup *MCGroup) Load(key interface{}) (err error) {
	switch key.(type) {
	case int64:
		mCGroup.Uid = key.(int64)
	default:
		log.WithFields(log.Fields{
			"method": "MCGroup_Load",
			"data":   key,
		}).Error("无效的key load")
		return errors.New("无效的key load")
	}
	return mCGroup.LoadData()
}

// 小组：加载数据
func (mCGroup *MCGroup) LoadData() (err error) {
	err = dbmodule.MgoDB.GameDB.FindOne("MCGroup", bson.M{"_id": mCGroup.Uid}, nil, &mCGroup)
	if err != nil {
		if err.Error() == "not found" {
			return err
		}
		return err
	}
	return
}

// 小组：更新数据
func (mCGroup *MCGroup) Update(val *MCGroup) {
	Cache.Put("MCGroup", val.Uid, val) //arG.GroupId.Hex()
	val.UpdateData()
}

// 小组：删除分组
func (mCGroup *MCGroup) Delete() (err error) {
	Cache.Remove("MCGroup", mCGroup.Uid)
	return dbmodule.MgoDB.GameDB.Remove("MCGroup", bson.M{"_id": mCGroup.Uid})
}

// 小组：删除所有分组
func (mCGroup *MCGroup) DeleteAll() (err error) {

	return dbmodule.MgoDB.GameDB.RemoveAll("MCGroup", nil)
}

// 小组：小组玩家人数
func (mCGroup *MCGroup) GetGamerLen() int {
	return len(mCGroup.LGamer)
}

// 小组：添加一群游戏玩家，直接添加num个玩家
func (mCGroup *MCGroup) AddMCGamers(mcGamers []*MCGamer) {
	mCGroup.LGamer = make([]*MCGamer, 0)
	mCGroup.MGamer = make(map[string]int64, 0)

	for idx, item := range mcGamers {
		mCGroup.LGamer = append(mCGroup.LGamer, item)
		mCGroup.MGamer[item.Uid.Hex()] = int64(idx)
	}
}

// 小组：添加游戏玩家
func (mCGroup *MCGroup) AddMCGamer(mcGamer *MCGamer) {
	// 超过100人，不添加
	if len(mCGroup.LGamer) > 100 {
		return
	}

	if len(mCGroup.LGamer) == 0 {
		mCGroup.LGamer = append(mCGroup.LGamer, mcGamer)
		mcGamer.RankId = 1
		mCGroup.MGamer[mcGamer.Uid.Hex()] = 0
		return
	}
	list := make([]*MCGamer, 0)
	val, _ := mCGroup.MGamer[mcGamer.Uid.Hex()]
	// 删除伤害更新的玩家
	list = append(mCGroup.LGamer[:val], mCGroup.LGamer[val+1:]...)

	flag := true
	rankId := int64(0)
	mCGroup.LGamer = make([]*MCGamer, 0)
	// 重新排名
	for _, item := range mCGroup.LGamer {
		rankId++
		if flag && mcGamer.Hurt >= item.Hurt {
			mcGamer.RankId = rankId
			list = append(list, mcGamer)
			mCGroup.MGamer[mcGamer.Uid.Hex()] = rankId - 1

			rankId++
			flag = false
		}

		mcGamer.RankId = rankId
		list = append(list, mcGamer)
		mCGroup.MGamer[mcGamer.Uid.Hex()] = rankId - 1
	}
}

// 小组：更新排名，玩家已在小组中
func (mCGroup *MCGroup) UpdateMCGamer(mcGamer *MCGamer) {
	list := make([]*MCGamer, 0)
	// 获取玩家在数组中的索引
	val, _ := mCGroup.MGamer[mcGamer.Uid.Hex()]
	// 删除更新的玩家
	list = append(mCGroup.LGamer[:val], mCGroup.LGamer[val+1:]...)

	flag := true
	rankId := int64(0)
	mCGroup.LGamer = make([]*MCGamer, 0)
	// 重新排名
	for _, item := range list {
		rankId++
		if flag && mcGamer.Hurt >= item.Hurt {
			mcGamer.RankId = rankId
			mCGroup.LGamer = append(mCGroup.LGamer, mcGamer)
			// 重置数组索引位置
			mCGroup.MGamer[mcGamer.Uid.Hex()] = rankId - 1

			rankId++
			flag = false
		}

		item.RankId = rankId
		mCGroup.LGamer = append(mCGroup.LGamer, item)
		// 重置数组索引位置
		mCGroup.MGamer[item.Uid.Hex()] = rankId - 1
	}
}

// 小组：对小组成员伤害排序，伤害降序
func (mCGroup *MCGroup) ReSort() {
	// 对小组成员进行排序
	sort.Slice(mCGroup.LGamer, func(i, j int) bool {
		return mCGroup.LGamer[i].Hurt > mCGroup.LGamer[j].Hurt
	})

	for idx, item := range mCGroup.LGamer {
		item.RankId = int64(idx + 1)
		mCGroup.MGamer[item.Uid.Hex()] = int64(idx)
	}
}

// 小组：获取游戏玩家
func (mCGroup *MCGroup) GetMCGamer(uid string) (mcGamer *MCGamer, ok bool) {
	if v, ok := mCGroup.MGamer[uid]; ok {
		mcGamer = mCGroup.LGamer[v]
		return mcGamer, true
	}
	return
}

// 小组：获取所有小组
func (mCGroup *MCGroup) GetMCGamerAll() (lMCGamer []*MCGamer, ok bool) {
	return mCGroup.LGamer, true
}

// 小组：获取前num名
func (mCGroup *MCGroup) GetMCGamerTop(num int) (lMCGamer []*MCGamer, ok bool) {
	lMCGamer = make([]*MCGamer, 0)
	ok = true
	length := len(mCGroup.LGamer)
	for i := 0; i < num; i++ {
		// 防止索引越界
		if i >= length {
			break
		}
		lMCGamer = append(lMCGamer, mCGroup.LGamer[i])
	}
	return
}

// 小组：删除游戏玩家
func (mCGroup *MCGroup) DelMCGamer(uid string) {
	if v, ok := mCGroup.MGamer[uid]; ok {
		// 删除列表中的该玩家
		mCGroup.LGamer = append(mCGroup.LGamer[:v], mCGroup.LGamer[v+1:]...)
		// 删除map中该玩家
		delete(mCGroup.MGamer, uid)
	}
}

// 小组：添加一群Boss
func (mCGroup *MCGroup) AddMCBossList(mcBossList []*MCBoss) {
	for _, item := range mcBossList {
		mCGroup.MBoss[item.Tid] = &MCBoss{
			Tid: item.Tid,
			Hp:  item.Hp,
		}
	}
}

// 小组：获取Boss
func (mCGroup *MCGroup) GetMCBoss(bossTid int64) (rboss *MCBoss, ok bool) {
	rboss, ok = mCGroup.MBoss[bossTid]
	return
}

// 小组：计算伤害
func (mCGroup *MCGroup) CalcHurt(uid string, hurt int64, bossTid int64) (rboss *MCBoss, ok bool) {
	// 小组修改数据，加锁
	mCGroup.rw.Lock()
	defer mCGroup.rw.Unlock()
	// 索引玩家位置
	gamerIdx, ok := mCGroup.MGamer[uid]
	if !ok {
		return
	}
	// 获取玩家信息
	gamer := mCGroup.LGamer[gamerIdx]
	// 获取Boss
	boss, ok := mCGroup.MBoss[bossTid]
	if !ok {
		return
	}
	// boss扣掉血量
	boss.Hp -= hurt
	// 累计玩家伤害
	gamer.Hurt += hurt
	// 累计每个Boss的伤害
	gamer.MEachBossHurt[bossTid] += hurt

	// 小组重新更新排名
	mCGroup.UpdateMCGamer(gamer)

	mCGroup.Update(mCGroup)
	gamer.Update(gamer)
	return
}

func NewMCGamer() cache.EntryI {
	return &MCGamer{}
}

// 玩家：
func (mCGamer *MCGamer) Save() (err error) {
	err = dbmodule.MgoDB.GameDB.Upsert("MCGamer", bson.M{"_id": mCGamer.Uid}, mCGamer)
	if err != nil {
		return
	}
	return
}

// 玩家：
func (mCGamer *MCGamer) Load(key interface{}) (err error) {
	switch key.(type) {
	case string:
		if key.(string) == "" {
			return errors.New("无效的key load, key empty")
		}
		mCGamer.Uid = bson.ObjectIdHex(key.(string))
	case bson.ObjectId:
		mCGamer.Uid = key.(bson.ObjectId)
	default:
		log.WithFields(log.Fields{
			"method": "MCGamer_Load",
			"data":   key,
		}).Error("无效的key load")
		return errors.New("无效的key load")
	}
	return mCGamer.LoadData()
}

// 玩家：加载数据
func (mCGamer *MCGamer) LoadData() (err error) {
	err = dbmodule.MgoDB.GameDB.FindOne("MCGamer", bson.M{"_id": mCGamer.Uid}, nil, &mCGamer)
	if err != nil {
		if err.Error() == "not found" {
			err = errors.NewErrcode(data.Errcode.NotFound, fmt.Sprintf("没有找到活动信息. id:%s", mCGamer.Uid.Hex()))
			return nil
		}
		return
	}
	return
}

// 玩家：更新数据
func (mCGamer *MCGamer) Update(val *MCGamer) {
	Cache.Put("MCGamer", val.Uid.Hex(), val)
	val.UpdateData()
}

// 玩家：删除玩家信息
func (mCGamer *MCGamer) Delete() (err error) {
	Cache.Remove("MCGamer", mCGamer.Uid.Hex())
	return dbmodule.MgoDB.GameDB.Remove("MCGamer", bson.M{"_id": mCGamer.Uid})
}

// 玩家：删除玩家信息
func (mCGamer *MCGamer) DeleteAll() (err error) {
	return dbmodule.MgoDB.GameDB.RemoveAll("MCGamer", nil)
}

// 活动：
func NewMCActiv() cache.EntryI {
	return &MCActiv{}
}

// 活动：
func (this *MCActiv) Save() (err error) {
	err = dbmodule.MgoDB.GameDB.Upsert("MCActiv", bson.M{"_id": this.Uid}, this)
	if err != nil {
		return
	}
	return
}

// 活动：
func (this *MCActiv) Load(key interface{}) (err error) {
	switch key.(type) {
	case int64:
		this.Uid = key.(int64)
	default:
		log.WithFields(log.Fields{
			"method": "MCActiv_Load",
			"data":   key,
		}).Error("无效的key load")
		return errors.New("无效的key load")
	}
	return this.LoadData()
}

// 活动：加载数据
func (this *MCActiv) LoadData() (err error) {
	err = dbmodule.MgoDB.GameDB.FindOne("MCActiv", bson.M{"_id": this.Uid}, nil, &this)
	if err != nil {
		if err.Error() == "not found" {
			err = errors.NewErrcode(data.Errcode.NotFound, fmt.Sprintf("没有找到活动信息. id:%d", this.Uid))
			return nil
		}
		return
	}
	return
}

// 活动：更新数据
func (this *MCActiv) Update(val *MCActiv) {
	err := dbmodule.MgoDB.GameDB.Upsert("MCActiv", bson.M{"_id": val.Uid}, val)
	if err != nil {
		return
	}
	return
}

func GetMCActiv(uid int64) *MCActiv {
	v, _ := Cache.Get("MCActiv", uid)
	return v.(*MCActiv)
}

// 活动：删除玩家信息
func (this *MCActiv) Delete() (err error) {
	Cache.Remove("MCActiv", this.Uid)
	return dbmodule.MgoDB.GameDB.RemoveAll("MCActiv", nil)
}

// 获取玩家信息
func (u *User) GetMCGamer() (r *MCGamer, ok bool) {
	v, ok := Cache.Get("MCGamer", u.Uid.Hex())
	if !ok {
		return
	}
	r = v.(*MCGamer)
	return
}

func GetMCGroup(uid int64) *MCGroup {
	v, _ := Cache.Get("MCGroup", uid)
	return v.(*MCGroup)
}

// 获取玩家信息
func (u *User) GetMCGroup() (r *MCGroup, ok bool) {
	gamer, ok := u.GetMCGamer()
	if !ok {
		return
	}
	v, ok := Cache.Get("MCGroup", gamer.GroupTid)
	if !ok {
		return
	}
	r = v.(*MCGroup)
	return
}

// 玩家：获取Boss
func (u *User) GetMCBoss(bossTid int64) (rboss *MCBoss, ok bool) {
	group, ok := u.GetMCGroup()
	if !ok {
		return
	}
	rboss, ok = group.GetMCBoss(bossTid)
	return
}
